#include "Utilidad.h"
#include "Cerdito.h"
#include "Catapulta.h"
#include "MonticuloHuevos.h"
#include "CajaVidrio.h"
#include "CajaMadera.h"
#include "CajaMetal.h"
#include "Manzana.h"
#include "Banana.h"
#include "Cereza.h"
#include "Perimetro.h"
#include "Piso.h"

using namespace TP::Juego::Arena::Utilidades;

Utilidad::Utilidad() {
	_posicion = NULL;
}

Utilidad::~Utilidad() {
	if (this->_rol)
		delete this->_rol;
}

Posicion* Utilidad::setPosicion(Posicion* pPosicion) {
	if (pPosicion)
		this->_posicion = pPosicion;
	return pPosicion;
}

Posicion* Utilidad::getPosicion() {
	return this->_posicion;
}

Rol* Utilidad::getRol() {
	return this->_rol;
}

Utilidad* Utilidad::deElementoXMLGenerico(TiXmlElement* pElemento) {
	Utilidad* utilidad = NULL;

	if (pElemento) {
		if (strcmp(ROL_CERDITO, pElemento->Value()) == 0) {
			utilidad = new Cerdito;
		}
		else if (strcmp(ROL_CATAPULTA, pElemento->Value()) == 0) {
			utilidad = new Catapulta;
		}
		else if (strcmp(ROL_MONTICULOHUEVOS, pElemento->Value()) == 0) {
			utilidad = new MonticuloHuevos;
		}
		else if (strcmp(ROL_CAJA_VIDRIO, pElemento->Value()) == 0) {
			utilidad = new CajaVidrio;
		}
		else if (strcmp(ROL_CAJA_MADERA, pElemento->Value()) == 0) {
			utilidad = new CajaMadera;
		}
		else if (strcmp(ROL_CAJA_METAL, pElemento->Value()) == 0) {
			utilidad = new CajaMetal;
		}
		else if (strcmp(ROL_MANZANA, pElemento->Value()) == 0) {
			utilidad = new Manzana;
		}
		else if (strcmp(ROL_BANANA, pElemento->Value()) == 0) {
			utilidad = new Banana;
		}
		else if (strcmp(ROL_CEREZA, pElemento->Value()) == 0) {
			utilidad = new Cereza;
		}
		else if (strcmp(ROL_PERIMETRO, pElemento->Value()) == 0) {
			utilidad = new Perimetro;
		}
		else if (strcmp(ROL_PISO, pElemento->Value()) == 0) {
			utilidad = new Piso;
		}

		if (utilidad)
			utilidad->deElementoXML(pElemento);
	}
	return utilidad;
}

string Utilidad::aXML() {
	TiXmlDocument* doc = new TiXmlDocument();
	TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "", "");
	doc->LinkEndChild(decl);

	doc->LinkEndChild(this->aElementoXML());

	TiXmlPrinter printer;
	doc->Accept(&printer);
	return printer.CStr();
}

string Utilidad::aXML(const string& pPath) {
	TiXmlDocument* doc = new TiXmlDocument(pPath.c_str());
	TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "", "");
	doc->LinkEndChild(decl);

	doc->LinkEndChild(this->aElementoXML());

	TiXmlPrinter printer;
	doc->Accept(&printer);
	return printer.CStr();
}

void Utilidad::parseXML(const string& pDescriptor) {
	TiXmlDocument doc;
	doc.Parse(pDescriptor.c_str(), 0, TIXML_ENCODING_UTF8);
	this->deElementoXML(doc.FirstChildElement());
}

TiXmlElement* Utilidad::aElementoXML() {
	TiXmlElement * element = new TiXmlElement(_rol->Nombre().c_str());

	// Serializo los atributos nativos.
	element->SetDoubleAttribute("vida", _vida);

	// Serializo la posicion.
	if (NULL != this->_posicion)
		element->LinkEndChild(this->getPosicion()->aElementoXML());
	else
		element->LinkEndChild(new TiXmlElement("NULL"));

	return element;
}

void Utilidad::deElementoXML(TiXmlElement* pElemento) {
	if (strcmp(pElemento->Value(), _rol->Nombre().c_str()) == 0) {

		// Hidrato los atributos nativos.
		pElemento->Attribute("vida", &_vida);
		//        pElemento->Attribute("puntaje", &_puntaje);

		// Hidrato la posicion.
		this->_posicion = NULL;

		if ("NULL" != pElemento->FirstChildElement()->ValueTStr()) {
			this->setPosicion(new Posicion());
			this->getPosicion()->deElementoXML(pElemento->FirstChildElement());
		}
	}
}

void Utilidad::decrementarEnergia(double cantidadEnergia) {
	if (cantidadEnergia >= _vida)
		destruir();
	else
		_vida -= cantidadEnergia;
}

double Utilidad::getVida() {
	return _vida;
}

void Utilidad::setVida(double vida) {
	_vida = vida;
}

void Utilidad::destruir() {
	_vida = 0;
}

bool Utilidad::destruido() const {
	return _vida <= 0;
}

void Utilidad::setEsEnemigo(bool esEnemigo) {
	_enemigo = esEnemigo;
}

bool Utilidad::esEnemigo() const {
	return _enemigo;
}